home *** CD-ROM | disk | FTP | other *** search
/ 9-Digit Zip Code Directory / 9-Digit Zip Code Directory (American Business Information) (ABIZIP-12).ISO / z4src.zip / Z4RANGE.CPP < prev    next >
C/C++ Source or Header  |  1995-09-14  |  11KB  |  360 lines

  1. //----------------------------------------------------------------------------
  2. //                            MODULE DESCRIPTION
  3. //
  4. //  Module:    z4numcp.cpp
  5. //   Title:    ZIP+4 Engine
  6. //  Notice:    John M. Weeder
  7. //                 Copyright (c) 1993. All rights reserved.
  8. //             This module contains proprietary information and should be 
  9. //                treated as confidential.
  10. //
  11. //----------------------------------------------------------------------------
  12. //                           MAINTENANCE HISTORY
  13. //
  14. // $Workfile$
  15. // $Revision$
  16. //   $Author$
  17. //     $Date$
  18. //      $Log$    
  19. //
  20. //----------------------------------------------------------------------------
  21. //                             MODULE NARRATIVE
  22. //
  23. //    This module contains code for the class Z4_RANGE.
  24. //
  25. //    The code in this module may be written in C++ or C.
  26. //
  27. //    This module is portable to:
  28. //        DOS 3.X+
  29. //        MS Windows 3.X+
  30. //        OS/2 2.X+
  31. //        OS/2 2.0 PM
  32. //
  33. //    The following compilers are supported:
  34. //        MSC 6.0A
  35. //        MSC/C++ 7.0
  36. //        Borland C++ 3.1 for DOS
  37. //        Borland C++ 1.0 for OS/2 2.X
  38. //
  39. //----------------------------------------------------------------------------
  40. #include <z4.h>
  41.  
  42.  
  43. //----------------------------------------------------------------------------
  44. //   Description:    Default constructor
  45. //    Parameters:
  46. //       Returns:    
  47. //----------------------------------------------------------------------------
  48. FN_M Z4_RANGE::Z4_RANGE()
  49. {
  50.     Z4_RANGE::Initialize(CL_INIT_CLASS);
  51. }
  52.  
  53.  
  54. //----------------------------------------------------------------------------
  55. //   Description:    Destructor
  56. //    Parameters:
  57. //       Returns:    
  58. //----------------------------------------------------------------------------
  59. FN_M Z4_RANGE::~Z4_RANGE()
  60. {
  61.     Z4_RANGE::Destroy(FALSE);
  62. }
  63.  
  64.  
  65. //----------------------------------------------------------------------------
  66. //   Description:    
  67. //    Parameters:
  68. //       Returns:    TRUE if successful.
  69. //----------------------------------------------------------------------------
  70. BOOL FN_M Z4_RANGE::Break(PCSZ pcsz, RZ4_NO range)
  71. {
  72.     memset(&range, 0, sizeof(range));
  73.     range.code = Z4_BOTH;
  74.     while (pcsz[0])
  75.         if (isalpha(pcsz[0]))                // Alpha
  76.             {
  77.             range.szNo[range.cNo][0] = pcsz[0];
  78.             // already has zero...range.szNo[range.cNo][1] = '\0'; 
  79.             range.afAlpha[range.cNo] = TRUE;
  80.             range.cNo++;
  81.             pcsz++;
  82.             }
  83.         else if (isdigit(pcsz[0]) && pcsz[1] == '/' && isdigit(pcsz[2]))
  84.             {                                        // Fraction
  85.             if (pcsz[3])                        // Fraction must be last element in address
  86.                 return FALSE;
  87.             if (pcsz[0] >= pcsz[2])            // Invalid fraction?
  88.                 return FALSE;
  89.  
  90.             range.cFract = ((pcsz[0] - '0') * 100) / (pcsz[2] - '0');
  91.             break;
  92.             }
  93.         else if (isdigit(pcsz[0]) && pcsz[1] != '/')
  94.             {                                        // Numeric
  95.             for (SIZET i = 0; isdigit(pcsz[i]) && pcsz[i+1] != '/'; ++i)
  96.                 ;
  97.  
  98.             if (MAX_RANGE - i)
  99.                 memset(range.szNo[range.cNo], '0', MAX_RANGE - i);
  100.             memcpy(range.szNo[range.cNo] + (MAX_RANGE - i), pcsz, i);
  101.             range.szNo[range.cNo][MAX_RANGE] = '\0';
  102.             pcsz += i;
  103.             range.code = ((range.szNo[range.cNo][MAX_RANGE-1] - '0') % 2) == 0 ? Z4_EVEN: Z4_ODD;
  104.             range.cNo++;
  105.             }
  106.         else if (pcsz[0] == '-' || pcsz[0] == '.')
  107.             {                                        // Dash or period
  108.             if (!range.cNo)
  109.                 return FALSE;
  110.  
  111.             while (pcsz[0] == '-' || pcsz[0] == '.')
  112.                 pcsz++;
  113.             range.afDash[range.cNo - 1] = TRUE;
  114.             }
  115.         else                                        // Invalid character
  116.             return FALSE;
  117.  
  118.     if (!range.cNo)                            // Invalid range
  119.         return FALSE;
  120.  
  121.     return TRUE;
  122. }
  123.  
  124.  
  125. //----------------------------------------------------------------------------
  126. //   Description:    
  127. //    Parameters:
  128. //       Returns:    TRUE if successful.
  129. //----------------------------------------------------------------------------
  130. BOOL FN_M Z4_RANGE::Compare()
  131. {
  132.     if (no.cNo != lo.cNo)
  133.         return FALSE;
  134.  
  135.     SIZET cHi = 0, cLo = 0;
  136.  
  137.     for (SIZET i = 0; i < no.cNo; ++i)
  138.         {
  139.                 //SHORT sLo = strcmp(no.szNo[i], lo.szNo[i]); org code
  140.                 //SHORT sHi = strcmp(no.szNo[i], hi.szNo[i]); org code
  141.                 INT sLo = strcmp(no.szNo[i], lo.szNo[i]);
  142.                 INT sHi = strcmp(no.szNo[i], hi.szNo[i]);
  143.         if (no.afAlpha[i] != lo.afAlpha[i] || sLo < 0 || sHi > 0)
  144.             return FALSE;
  145.         if (sLo == 0)
  146.             cLo++;
  147.         if (sHi == 0)
  148.             cHi++;
  149.         }
  150.     if (cHi == hi.cNo && no.cFract > hi.cFract)
  151.         return FALSE;
  152.     if (cLo == lo.cNo && no.cFract < lo.cFract)
  153.         return FALSE;
  154.     return TRUE;
  155. }
  156.  
  157.  
  158. //----------------------------------------------------------------------------
  159. //   Description:    Destroy object. Free any resources used by object.
  160. //                          Normally called by destructor.
  161. //                        Should allow multiple calls from various classes.
  162. //                        A class should almost always re-init its variables when 
  163. //                        it is destroyed to prevent accidents.
  164. //    Parameters:    fDestroyAll        Destroy parents also?
  165. //                                            Default is TRUE.
  166. //       Returns:    TRUE if successful.
  167. //----------------------------------------------------------------------------
  168. BOOL FN_M Z4_RANGE::Destroy(BOOL fDestroyAll)
  169. {
  170.     Z4_RANGE::Initialize(CL_INIT_CLASS_VARS);
  171.     if (fDestroyAll)                            // Destroy parent.
  172.         Z4_RANGE_PARENT::Destroy(fDestroyAll);
  173.     return TRUE;
  174. }
  175.  
  176.  
  177. //----------------------------------------------------------------------------
  178. //   Description:    
  179. //    Parameters:
  180. //       Returns:    TRUE if successful.
  181. //----------------------------------------------------------------------------
  182. BOOL FN_M Z4_RANGE::Exception()
  183. {
  184.     return lo.cNo == 1                        // Hi/lo range is single numeric
  185.         && !lo.afAlpha[0]
  186.         && no.cNo == 2                            // Number is numeric and single alpha
  187.         && !no.afAlpha[0] 
  188.         && no.afAlpha[1]                        // And numeric range is valid
  189.         && strcmp(no.szNo[0], lo.szNo[0]) >= 0
  190.         && strcmp(no.szNo[0], hi.szNo[0]) <= 0
  191.         && no.cFract >= lo.cFract
  192.         && no.cFract <= hi.cFract;
  193. }
  194.  
  195.  
  196. //----------------------------------------------------------------------------
  197. //   Description:    Initialize object. 
  198. //                          Normally called by constructor.
  199. //                        Should allow multiple calls from various classes.
  200. //    Parameters:    sInit        Initialization code. May be one of the following:
  201. //                                        CL_INIT_CLASS            Reset class variables and
  202. //                                                                    and dynamic allocations for
  203. //                                                                    this class only.
  204. //                                        CL_INIT_CLASS_VARS    Reset class variables for
  205. //                                                                    this class only.
  206. //                                        CL_INIT_VARS            Reset class variables for
  207. //                                                                    this class only.
  208. //                                        CL_INIT_ALL                Initialize class and all 
  209. //                                                                    parent class, including
  210. //                                                                    dynamic memory allocation.
  211. //                                    Default is CL_INIT_ALL
  212. //       Returns:    TRUE if successful.
  213. //----------------------------------------------------------------------------
  214. BOOL FN_M Z4_RANGE::Initialize(SHORT sInit)
  215. {
  216.     if (sInit == CL_INIT_VARS || sInit == CL_INIT_ALL)
  217.         Z4_RANGE_PARENT::Initialize(sInit);
  218.  
  219.     return TRUE;
  220. }
  221.  
  222.  
  223. //----------------------------------------------------------------------------
  224. //   Description:    
  225. //    Parameters:
  226. //       Returns:    TRUE if successful.
  227. //----------------------------------------------------------------------------
  228. BOOL FN_M Z4_RANGE::Input(PSZ pszBuf, PCSZ pcszIn, SIZET cMax)
  229. {
  230.     Assert(pcszIn);
  231.     for (; pcszIn[0]; ++pcszIn)
  232.         {
  233.         if (!cMax)                                // Range is too large
  234.             return FALSE;
  235.         if (!isspace(*pcszIn))                // Copy and eliminate spaces
  236.             *pszBuf++ = *pcszIn;
  237.         }
  238.     pszBuf[0] = '\0';
  239.     return TRUE;
  240. }
  241.  
  242.  
  243. //----------------------------------------------------------------------------
  244. //   Description:    
  245. //    Parameters:
  246. //       Returns:    TRUE if successful.
  247. //----------------------------------------------------------------------------
  248. BOOL FN_M Z4_RANGE::Primary(PCSZ pcszNo, PCSZ pcszLo, PCSZ pcszHi, Z4_CODE code)
  249. {
  250.     Assert(pcszNo);
  251.     if (pcszLo == NULL || !pcszLo[0])    // No range specified?
  252.         return pcszNo[0] == '\0';
  253.     if (pcszHi == NULL || !pcszHi[0])    // No high range
  254.         pcszHi = pcszLo;
  255.                                                // Clean up input
  256.     if (!Input(szNo, pcszNo, MAX_PRI_NO)
  257.     || !Input(szLo, pcszLo, MAX_PRI_NO)
  258.     || !Input(szHi, pcszHi, MAX_PRI_NO))
  259.         return FALSE;
  260.  
  261.     if (!Break(szNo, no)                        // Break into ranges
  262.     || !Break(szLo, lo)
  263.     || !Break(szHi, hi))
  264.         return FALSE;
  265.  
  266.     if (strcmp(szNo, szLo) == 0            // Watch for exact match to 
  267.     || strcmp(szNo, szHi) == 0)            //  top or bottom of range
  268.         return TRUE;
  269.  
  270.     if (!Validate())                            // Validate lo/hi range
  271.         return FALSE;
  272.                                                     // Check odd/even flag
  273.     if (code != Z4_BOTH && no.code != code)
  274.         return FALSE;
  275.  
  276.     if (Exception())                            // Single alpha exception?
  277.         return TRUE;
  278.  
  279.     return Compare();
  280. }
  281.  
  282.  
  283. //----------------------------------------------------------------------------
  284. //   Description:    
  285. //    Parameters:
  286. //       Returns:    TRUE if successful.
  287. //----------------------------------------------------------------------------
  288. BOOL FN_M Z4_RANGE::Secondary(PCSZ pcszNo, PCSZ pcszLo, PCSZ pcszHi, Z4_CODE code)
  289. {
  290.     Assert(pcszNo);
  291.     if (pcszLo == NULL || !pcszLo[0])    // No range specified?
  292.         return pcszNo[0] == '\0';
  293.     if (pcszHi == NULL || !pcszHi[0])    // No high range
  294.         pcszHi = pcszLo;
  295.                                                // Clean up input
  296.     if (!Input(szNo, pcszNo, MAX_SEC_NO)
  297.     || !Input(szLo, pcszLo, MAX_SEC_NO)
  298.     || !Input(szHi, pcszHi, MAX_SEC_NO))
  299.         return FALSE;
  300.  
  301.     if (!Break(szNo, no)                        // Break into ranges
  302.     || !Break(szLo, lo)
  303.     || !Break(szHi, hi))
  304.         return FALSE;
  305.  
  306.     if (strcmp(szNo, szLo) == 0            // Watch for exact match to 
  307.     || strcmp(szNo, szHi) == 0)            //  top or bottom of range
  308.         return TRUE;
  309.  
  310.     if (!Validate())                            // Validate lo/hi range
  311.         return FALSE;
  312.                                                     // Check odd/even flag
  313.     if (code != Z4_BOTH && no.code != code)
  314.         return FALSE;
  315.  
  316.     if (Exception())                            // Single alpha exception?
  317.         return TRUE;
  318.  
  319.     return Compare();
  320. }
  321.  
  322.  
  323. //----------------------------------------------------------------------------
  324. //   Description:    
  325. //    Parameters:
  326. //       Returns:    TRUE if successful.
  327. //----------------------------------------------------------------------------
  328. BOOL FN_M Z4_RANGE::Validate()
  329. {
  330.     if (lo.cNo != hi.cNo)
  331.         return FALSE;
  332.  
  333.     BOOL fRanged = FALSE;
  334.     for (SIZET i = 0; i < lo.cNo; ++i)
  335.         {
  336.         if (lo.afDash[i] != hi.afDash[i]
  337.         || lo.afAlpha[i] != hi.afAlpha[i])
  338.             return FALSE;
  339.  
  340.                 //SHORT sResult = strcmp(lo.szNo[i], hi.szNo[i]); org code
  341.                 INT sResult = strcmp(lo.szNo[i], hi.szNo[i]);
  342.         if (sResult > 0)                        // Invalid range
  343.             return FALSE;
  344.         if (sResult)
  345.             {
  346.             if (fRanged)                        // More than one field ranged
  347.                 return FALSE;
  348.  
  349.             fRanged = TRUE;
  350.             }
  351.         }
  352.     if (!fRanged)                                // If ranges are equal, check fractional
  353.         if (lo.cFract > hi.cFract)
  354.             return FALSE;
  355.     return TRUE;
  356. }
  357. //----------------------------------------------------------------------------
  358. //------------------------------- End of File --------------------------------
  359. //----------------------------------------------------------------------------
  360.